package com.wuda.segmentation;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

/**
 * <p>
 * 最大匹配分词法
 * </p>
 * 
 * @author wuda
 * 
 */
public class MaxMatchSegmenter implements Segmenter {

	private int maxTermLength = 5; // 最大词长

	private Set<String> dictionary = null; // 词典

	public MaxMatchSegmenter(Set<String> dictionary) {
		this.dictionary = dictionary;
	}

	/**
	 * <p>
	 * 逆向最大匹配
	 * </p>
	 */
	public List<Token> bmm(String input) {
		int length = input.length();
		int position = length; // 从后向前
		int startIndex = 0;
		String term = null;
		List<Token> segmentTokens = new ArrayList<Token>();
		while (position > 0) {
			startIndex = position - maxTermLength;
			if (startIndex < 0) {
				startIndex = 0;
			}
			term = input.substring(startIndex, position); // 取出候选字符串
			int termLength = term.length();
			int moveCount = 0; // term去掉最左边字符的次数
			while (termLength >= 2) { // 保证term不能为一个单字,所以termLeng>=2
				if (isInDictionary(term)) {
					Token segToken = new Token(term.toCharArray(), startIndex
							+ moveCount, position);
					segmentTokens.add(segToken);
				}
				if (termLength == 2) { // 单字在这里不认为是“词”
					break;
				}
				term = term.substring(1, termLength); // 将term最左边的字符去掉,相对于在取出的候选词中也做“回溯”
				moveCount++;
				termLength--;
			}

			position--; // 注意每次只是往前移动一位,而不是maxTermLength位,就是带有“回溯”的意思
		}
		return segmentTokens;
	}

	/**
	 * <p>
	 * 获得当前设置的最大词长
	 * </p>
	 * 
	 * @return 最大词长
	 */
	public int getMaxTermLength() {
		return maxTermLength;
	}

	/**
	 * <p>
	 * 设置最大词长
	 * </p>
	 * 
	 * @param maxTermLength
	 *            最大词长
	 */
	public void setMaxTermLength(int maxTermLength) {
		this.maxTermLength = maxTermLength;
	}

	/**
	 * <p>
	 * 判断给定的字符串是否在字典中
	 * </p>
	 * 
	 * @param term
	 *            单词
	 * @return true-如果在字典中
	 */
	public boolean isInDictionary(String term) {
		return dictionary.contains(term);
	}

	@Override
	public List<Token> seg(String input) {
		return bmm(input); // 首先分词
	}

}
